package com.zys.background.common.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zys
 * @since 2022-11-23
 */
@Slf4j
@EnableRabbit
@Configuration
@EnableAutoConfiguration
public class RabbitmqConfiguration implements ApplicationContextAware {

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
    rabbitTemplate.setConfirmCallback(confirmCallback());
    rabbitTemplate.setReturnsCallback(returnsCallback());
    rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
  }

  @Bean
  public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate) {
    return new RepublishMessageRecoverer(rabbitTemplate);
  }

  private static RabbitTemplate.ConfirmCallback confirmCallback() {
    return (correlationData, ack, cause) -> {
      String id = correlationData != null ? correlationData.getId() : "";
      if (ack) {
        log.info("交换机已经收到 id 为:{} 的消息", id);
      } else {
        log.info("交换机还未收到 id 为:{} 消息,由于原因:{}", id, cause);
      }
    };
  }

  private static RabbitTemplate.ReturnsCallback returnsCallback() {
    return returnedMessage -> {
      log.info("\n");
      log.info("交换机: {}", returnedMessage.getExchange());
      log.info("消息体: {}", returnedMessage.getMessage());
      log.info("响应码: {}", returnedMessage.getReplyCode());
      log.info("响应信息: {}", returnedMessage.getReplyText());
      log.info("routingKey: {}", returnedMessage.getRoutingKey());
      log.info("\n");
    };
  }
}
